<!--* Created by ljx on 2025/05/27.-->
<!--* 所有页面对于table设置固定高度才能生成scrollbar-->
<!--* 本js为通用的设置当前页面的table的高度-->
<!--* 通过获取页面的高度减去固定的页面距顶部的高度，头部与内容区域分隔线的高度，通用间距padding-->
<!--* 页面基本构成:-->
<!--顶部黑色横条 + tags页签 + searchForm(头部容器) + operation(内容的按钮横条容器) + Table + BottomBar(公用底部)-->
<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, nextTick } from "vue";
import ResizeObserver from "resize-observer-polyfill";
import { useVModel } from "@vueuse/core";
import { useSettingStoreHook } from "@/store/modules/settings";
import { storeToRefs } from "pinia";
import router from "@/router";
import {
  TOP_TAB,
  TOP_NAV,
  LINE_GAP,
  PADDING,
  BOTTOM,
  BASE_FONTSIZE,
  MARGIN
} from "@/utils/staticData";

defineOptions({
  name: "PageWrapper"
});

const settingsStore = useSettingStoreHook();
const { rootSize, hiddenSideBar } = storeToRefs(settingsStore);

const props = defineProps({
  height: { default: 0, type: Number, required: true }, // 最终获取的内容高度
  headerDomIdx: { default: 0, type: Number }, // .wrapper-header的索引
  isResize: { default: true, type: Boolean }, // 是否展示版心
  isShowHeader: { default: true, type: Boolean }, // 是否展示头部
  isShowLine: { default: true, type: Boolean }, // 是否展示分割线
  isShowContent: { default: true, type: Boolean }, // 是否展示内容
  isShowPagination: { default: true, type: Boolean }, // 是否展示分页器
  noTopPadding: { default: false, type: Boolean }, // wrapper-content顶部是否需要padding
  isShowBottom: { default: true, type: Boolean } // 是否展示底部
});

const emits = defineEmits(["table", "update:height"]);
const tableFixHeight = useVModel(props, "height", emits);
const $resizeObserver = ref<ResizeObserver>();
const dom = ref(null);

onBeforeUnmount(() => {
  removeSearchDomListener();
  window.removeEventListener("resize", setHeight, false);
});

const initData = () => {
  dom.value = document.querySelectorAll(".wrapper-form")[0];
  addSearchDomListener();
  nextTick(() => {
    setHeight();
    window.addEventListener("resize", setHeight, false);
  });
};

const setHeight = () => {
  const clientHeight = document.body.clientHeight;
  const searchFormDom =
    document.querySelectorAll(".wrapper-header")[props.headerDomIdx]; // 头部容器
  const operationDom = document.querySelectorAll(".wrapper-operation")
    ? document.querySelectorAll(".wrapper-operation")[0]
    : null; // 内容的按钮横条容器
  const formHeight = searchFormDom ? searchFormDom.offsetHeight : 0; // 头部容器的高度
  const operationHeight = operationDom ? operationDom.offsetHeight : 0; // 内容的按钮横条的高度
  const footerHeight = props.isShowBottom
    ? BOTTOM
    : document.querySelectorAll(".wrapper-footer")[0]?.offsetHeight + LINE_GAP;
  const gapHeight = props.isShowLine ? LINE_GAP : 0;
  const topNavHeight = !!hiddenSideBar.value ? 0 : TOP_NAV;
  tableFixHeight.value =
    clientHeight -
    formHeight -
    operationHeight -
    ((topNavHeight +
      TOP_TAB +
      MARGIN +
      (props.noTopPadding ? PADDING / 2 : PADDING) +
      footerHeight +
      gapHeight) *
      rootSize.value) /
      BASE_FONTSIZE;
};

// 绑定监听头部容器宽度变化的事件
const addSearchDomListener = () => {
  $resizeObserver.value = new ResizeObserver(entries => {
    const contentRect = entries[0].contentRect;
    if (!(contentRect.width || contentRect.height)) return;
    setHeight();
  });
  if (dom.value) $resizeObserver.value.observe(dom.value);
};

// 解绑监听头部容器宽度变化的事件
const removeSearchDomListener = () => {
  if (dom.value) $resizeObserver.value.unobserve(dom.value);
  $resizeObserver.value = null;
};

defineExpose({
  initData
});
</script>

<template>
  <div class="Wrapper">
    <header
      v-if="isShowHeader"
      class="wrapper-header"
      :class="{ noBorderRadisBottom: !isShowLine }"
    >
      <slot name="header" />
    </header>
    <div v-if="isShowLine" class="line" />
    <nav
      v-if="isShowContent"
      class="wrapper-content"
      :class="{
        noTopPadding: noTopPadding,
        noBorderRadisTop: !isShowLine && isShowHeader
      }"
    >
      <slot name="content" />
    </nav>
    <div v-if="!isShowBottom" class="line" />
    <footer v-if="!isShowBottom" class="wrapper-footer">
      <slot name="footer" />
    </footer>
  </div>
</template>

<style scoped lang="scss">
.Wrapper {
  .wrapper-header {
    padding: 24px 24px 8px 24px;
    background: #fff;
    border-radius: 8px;
    &.noBorderRadisBottom {
      border-radius: 8px 8px 0 0;
      padding-bottom: 0;
    }
  }
  .wrapper-content {
    padding: 24px 24px;
    background: #fff;
    border-radius: 8px;
    &.noBorderRadisTop {
      border-radius: 0 0 8px 8px;
    }
  }
  .noTopPadding {
    padding-top: 0;
  }
  .line {
    height: 16px;
    width: 100%;
  }
}
</style>
